package server;
import java.io.IOException;

import javax.net.ssl.SSLSocket;

import common.Lector_socket;
import common.Mensaje;

/**
 * Clase que atiende al cliente admin (a pesar del nombre no extiende a thread)
 * @author Matias
 *
 */
public class ThreadServerAdmin {
	
	private static final int TIME_OUT_CIERRE= 3000;
	
	private SSLSocket conexion_entrante;
	private ServidorPrincipal server;
	private Lector_socket lector;
	
	private int estado_interno;
	
	private Log log;
	
	/**
	 * Constructor de la clase. Recibe el socketSSL que utilza como conexi�n y el servidor ppal al que esta vinculado.
	 * @param s : socket SSL
	 * @param serv : servidor al que est� vinculado
	 */
	public ThreadServerAdmin(SSLSocket s, ServidorPrincipal serv, Log l){
		log = l;
		conexion_entrante=s;
		server = serv;
		lector = new Lector_socket(conexion_entrante);
		//System.out.println("SERVER ADMIN: Se creo instancia de thread para atender al admin");
		log.writeLog(Log.INFO, "CLIENTE ADMIN", "Constructor", "Se creo instancia de thread para atender al admin");
	}

	public void atender_admin(){
		
		boolean fin=server.get_fin_sesion();
		while(!fin){
			
			//System.out.println("SERVER ADMIN: Estado "+server.get_estado());
			Mensaje msj = lector.leer_msj();
			
			if(msj!=null){ // es decir, si no se cort� la conexi�n
				//System.out.println("MSJ DE ADMIN: "+msj.getTipo_msj()+" "+msj.getContenido());
				 
				estado_interno = server.get_estado();
				Mensaje rta=new Mensaje();
				 
				switch(estado_interno){
				 
				 	case 0:{
				 		// momento en que se crean los threads para atender al admin y clientes 
				 		break;
				 	}
				 	case 1 : {
				 		 //Se espera por msj de inicio de sesi�n 
				 		if(msj.getTipo_msj().equals(Mensaje.TIPO_INICIO_SESION)){ // si recibe inicio de sesi�n devuelve OK
				 			
							rta.setTipo_msj(Mensaje.TIPO_OK);
							rta.setContenido("The hammer of the gods\nwill drive our ships to new lands\nto fight the horde, singing an criying\nValhalla i'm comming!!!\n by Led Zeppelin");// ESTO ES UNA PRUEBA!!!!!!!!!!!!!!
							
							server.setSesionActual();
							server.set_estado(2);
							//System.out.println("SERVER ADMIN: Admin da comienzo a la sesi�n");
							log.writeLog(Log.INFO, "CLIENTE ADMIN", "ESTADO 1", "Se da comienzo a la sesi�n");
						
				 		}else{ // cualquier otro msj lo considera error
							rta.setTipo_msj(Mensaje.TIPO_ERROR);
							rta.setContenido("ERROR en estado 1\n\tse espera msj del tipo 'INICIO SESION'\n\t bye!");// ESTO ES UNA PRUEBA!!!!!!!!!!!!!!
							
						}
				 		 break;}
				 	case 2 : {
				 		// verificaci�n de quor�m 
				 		//*msj = lector.leer_msj();
				 		if(msj.getTipo_msj().equals(Mensaje.TIPO_FIN_ADMISION_CLIENTES)){
				 			rta.setTipo_msj(Mensaje.TIPO_OK);
				 			synchronized (server) {
				 				server.notify();
							}
				 		}else if(msj.getTipo_msj().equals(Mensaje.TIPO_HAY_QUORUM)){
				 			// ac� deberia preguntarle al servidor si hay quorum y responder S� o NO <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
				 			//synchronized (server) {
								//	server.notify();
									if(server.hayQuorum()){
						 				rta.setTipo_msj(Mensaje.TIPO_SI);
						 				server.set_estado(3);
						 				//System.out.println("SERVER ADMIN: Hay quorum");
						 				log.writeLog(Log.INFO, "CLIENTE ADMIN", "ESTADO 2", "Hay quorum");
						 				
						 			}else{// en caso de que no se alcance quorum se pasa a estado 8
						 				rta.setTipo_msj(Mensaje.TIPO_NO);
						 				server.set_estado(8); // se cierra sesion
						 				log.writeLog(Log.INFO, "CLIENTE ADMIN", "ESTADO 2", "NO hay quorum");
						 			}
								
							//}
				 		}else{ // cualquier otro msj lo considera error
				 			rta.setTipo_msj(Mensaje.TIPO_ERROR);
							
						}
				 		break;
				 	}
				 	case 3 : {
				 		// Inicia tema 
				 		if(msj.getTipo_msj().equals(Mensaje.TIPO_INICIO_TEMA)){
				 			rta.setTipo_msj(Mensaje.TIPO_OK);
							server.definirTemaActual(msj.getContenido());
							
							synchronized (this) {
								try {
									this.wait();
								} catch (InterruptedException e) {
									System.err.println(e.getMessage());
								}
							}
							
							server.set_estado(4);
							//System.out.println("SERVER ADMIN: Se da inicio a tema");
							log.writeLog(Log.INFO, "CLIENTE ADMIN", "ESTADO 3", "Se da inicio a tema");
						
				 		}else if(msj.getTipo_msj().equals(Mensaje.TIPO_HAY_RTDOS)){ // admin pregunta si ya estan los rtdos, se le responde que NO
				 			rta.setTipo_msj(Mensaje.TIPO_NO);
							
						}else{ // cualquier otro msj lo considera error
							rta.setTipo_msj(Mensaje.TIPO_ERROR);
						}
				 		break;
				 	}
				 	case 4 : {// ???????????????????????????????????????????????????????
				 		// che, y ac� que hacemos??? bueno... si pregunta por votaci�n respondemos uqe s�, cualquier otra cosa respondemos error
				 		// IMPORTANTE: server gral es responsable de pasar a siguiente estado
				 		//*msj = lector.leer_msj();
				 		if(msj.getTipo_msj().equals(Mensaje.TIPO_HAY_VOTACION)){ // admin pregunta si ahoa hay votaci�n, se le responde que SI---PUEDE QUE ESTE DE MAS!!!!!!!!!
				 			rta.setTipo_msj(Mensaje.TIPO_NO);
							//server.set_estado(3);
							//System.out.println("SERVER ADMIN: Pregunto si actualmente hay votacion");
				 			//log.writeLog(Log.INFO, "CLIENTE ADMIN", "ESTADO 4", "Pregunta si actualmente hay votacion");
							
						}else if(msj.getTipo_msj().equals(Mensaje.TIPO_HAY_RTDOS)){ // admin pregunta si ya estan los rtdos, se le responde que NO
				 			rta.setTipo_msj(Mensaje.TIPO_NO);
						}else{ // cualquier otro msj lo considera error
							rta.setTipo_msj(Mensaje.TIPO_ERROR);
						}
				 		break;
				 	}
				 	case 5 : {
				 		// IMPORTANTE: server gral es responsable de pasar a estado 6 tras terminar de procesar votos
				 		if(msj.getTipo_msj().equals(Mensaje.TIPO_HAY_VOTACION)){ // admin pregunta si ahoa hay votaci�n, se le responde que SI
				 			rta.setTipo_msj(Mensaje.TIPO_SI);
							//System.out.println("SERVER ADMIN: Pregunto si actualmente hay votacion");
							
						}else if(msj.getTipo_msj().equals(Mensaje.TIPO_HAY_RTDOS)){ // admin pregunta si ya estan los rtdos, se le responde que NO
				 			rta.setTipo_msj(Mensaje.TIPO_NO);
						}else{ // cualquier otro msj lo considera error
							rta.setTipo_msj(Mensaje.TIPO_ERROR);
						}
				 		
				 		break;}
				 	case 6 : {
				 		// IMPORTANTE: server ppal responsable por pasara estado 7
				 		if(msj.getTipo_msj().equals(Mensaje.TIPO_HAY_RTDOS)){
				 			
				 			synchronized (this) {
								try {
									while(!server.hayRtdos){ // bloqueo el thread hasta que server ppal termine de procesar los rtdos
										this.wait();
									}
								} catch (InterruptedException e) {}
							}
				 			
				 			synchronized (server) {
								server.notify(); // desbloqueo a server ppal para que pase al estado 7
								rta.setTipo_msj(Mensaje.TIPO_SI);
					 			rta.setContenido(server.obtenerRtdos());
					 			//server.set_estado(7);
								//System.out.println("SERVER ADMIN: Pregunto si actualmente hay votacion");
							}
							
						}else{ // cualquier otro msj lo considera error
							rta.setTipo_msj(Mensaje.TIPO_ERROR);
							
						}
				 		break;}
				 	case 7:{
				 		if(msj.getTipo_msj().equals(Mensaje.TIPO_NUEVO_TEMA)){
				 			rta.setTipo_msj(Mensaje.TIPO_OK);
				 			server.set_estado(3);
							//System.out.println("SERVER ADMIN: Admin inicia nuevo tema");
				 			log.writeLog(Log.INFO, "CLIENTE ADMIN", "Estado 7", "Inicia nuevo tema");
							
						}else if(msj.getTipo_msj().equals(Mensaje.TIPO_CIERRE_SESION)){
				 			rta.setTipo_msj(Mensaje.TIPO_OK);
				 			server.set_estado(8);
							//System.out.println("SERVER ADMIN: Admin cierra sesion");
				 			log.writeLog(Log.INFO, "CLIENTE ADMIN", "Estado 7", "Cierra sesi�n");
							
						}else if(msj.getTipo_msj().equals(Mensaje.TIPO_HAY_VOTACION)){
				 			rta.setTipo_msj(Mensaje.TIPO_NO_HAY_QUORUM);
				 		}else { // cualquier otro msj lo considera error
							rta.setTipo_msj(Mensaje.TIPO_ERROR);
						}
						 break;
					}
				 	case 8:{
				 		rta.setTipo_msj(Mensaje.TIPO_CIERRE_SESION);
						
						// cierre de conexion
						fin = true;
						
						break;
					 }
				 } // fin-switch
				
				//if(!fin)
					//lector.enviar_msj(rta);
				lector.enviar_msj(rta);
				
				
			}else{ // else de if(msj!=null) es decir, se corto la conexi�n!
				fin = true;
				//System.err.println("ADMIN : se cort� la conexi�n con el cliente admin. Se cerrar� la conexi�n.");
				log.writeLog(Log.INFO, "CLIENTE ADMIN", "Estado 8", "Se cort� la conexi�n, se proceder� a cerrar la conexi�n");
				server.set_estado(8);
			}
			
		} // fin-while
		
		// --- CIERRE CONEXION ---
		// sleep para dar tiempo a que cliente reciba la rta
		try {
			Thread.sleep(TIME_OUT_CIERRE);
		} catch (InterruptedException e) {
		}
		
		lector.cerrar();
		
		try {
			conexion_entrante.close();
		} catch (IOException e) {
		}
		//System.out.println("SERVER ADMIN: se cerro la conexi�n");
		log.writeLog(Log.INFO, "CLIENTE ADMIN", "Cierre conexi�n", "Se cerr� la conexi�n correctamente");
	} // fin-atender-admin()

}